package controllers;

import java.util.LinkedList;
import java.util.List;

import models.Comment;
import models.Entities;
import models.Idea;
import models.Log;
import models.Organization;
import models.Permission;
import models.Topic;
import models.User;
import play.mvc.Controller;

/**
 * Entity Controller that links the views of the entity and the model class
 * entites
 * 
 * @author Mai Abu-El Seoud
 * 
 */
public class Entity extends Controller {

	/**
	 * The organization id in which the entity will be created in
	 * 
	 * @author Mai Abu-El Seoud
	 */
	public static long entityOrganization;

	/**
	 * renders a HTML page that takes the input parameters for creating an
	 * entity from the organization lead
	 * 
	 * @param OrganizationId
	 *            The Organization id, in which the entity will be created in
	 * @author Mai Abu-El Seoud
	 * 
	 */
	public static void createEntity(Long organizationId) {
		entityOrganization = organizationId;

		render(organizationId);
	}

	/**
	 * directs the user to a page that ensures on creating the entity and save
	 * the created entity in the database and then call the method
	 * viewEntity(Long entityId) with the entity id
	 * 
	 * @param entity
	 *            The entity that will be created
	 * @author Mai Abu-El seoud
	 * 
	 */
	public static void assignOrganizer(Entities entity) {
		Organization organization = Organization.findById(entityOrganization);
		boolean found = Entities.checkName(entity.entityName, organization);
		if (found == false) {
			flash.error("There is an already created entity with that name");
			Entity.createEntity(entityOrganization);
		}
		entity.organization = organization;
		entity.save();
		Log log = new Log(entity.organization, entity.organization.lead,
				" has created a new Entity of title: " + entity.entityName
						+ " in the organization.");
		log.save();
		addSubscriber(entity.id);
		viewEntity(entity.id);
	}

	/**
	 * takes parameters from the user and edited the entity with the new
	 * parameters and save it in the database and render editEntity.html
	 * 
	 * @param entityId
	 *            the entity id that will be edited
	 * @author Mai Abu-El seoud
	 * 
	 */
	public static void editEntity(Long entityId) {
		Entities entity = Entities.findById(entityId);
		boolean check = entity.isLocked;
		render(entity, check);
	}

	/**
	 * renders a page that view the entity that was edited with the new values
	 * 
	 * @param entityId
	 *            The edited entity
	 * @author Mai Abu-El Seoud
	 */
	public static void entityedited(Long entityId) {
		Entities entity = Entities.findById(entityId);
		Organization organization = entity.organization;
		String entityName = params.get("name");
		boolean found = false;
		if (entityName.equalsIgnoreCase(entity.entityName)) {
			found = true;
		} else {
			found = Entities.checkName(entityName, organization);
			if (found == false) {
				flash.error("There is an already created entity with that name");
				editEntity(entity.id);
			}
		}
		Log log = new Log(entity.organization, null, " Entity "
				+ entity.entityName + " has been changed to " + entityName);
		log.save();
		entity.entityName = params.get("name");
		String status = params.get("status");

		if (status.matches("Locked")) {

			entity.isLocked = true;
		}
		if (status.matches("Unlocked")) {

			entity.isLocked = false;

		}

		entity.save();
		viewEntity(entity.id);
	}

	/**
	 * renders a page that view the entity with it's parameters
	 * 
	 * [Authorization] Shows the lock/unlock button for organization lead and
	 * entity organizer only by getting the permission of the logged in user and
	 * check his type
	 * 
	 * 
	 * 
	 * @param entityId
	 *            The entity id that will be rendered
	 * @author Mai Abu-El Seoud
	 * @author Mohamed Abdel Kader
	 * 
	 */
	public static void viewEntity(Long entityId) {

		boolean canInviteOrganizers= true;
		boolean assignOrganizer= true;
		boolean blockIdeaDeveloper = true;
		Entities entity = Entities.findById(entityId);
		Organization organization = entity.organization;
		String idString = session.get("userId");
		if (idString == null) {
			Home.home(null, null, "Please Login");
		}
		Long userId = Long.parseLong(idString);
		User user = User.findById(userId);

		boolean isSubscriber = entity.userinSubscribers(user);
		List<User> alluser = entity.getSubscribers();
		boolean permit = true;
		boolean authorized = false;
		Permission permission = User.userPermissionInOrganization(user.id,
				organization.id);
		String role = permission.aUserType;
		if (role.equals("organizer"))
		{
			Permission permissionEntity = User.userPermissionInEntity(user.id,
					organization.id, entityId);
			 canInviteOrganizers = permissionEntity.inviteToBeOrganizer;
			//System.out.println(canInviteOrganizers + "invite");
			 assignOrganizer =permissionEntity.addOrganizer;
			 blockIdeaDeveloper =permissionEntity.blockView;

		}
		
		boolean access = false;
		for (int counter = 0; counter < entity.entityOrganizers.size(); counter++) {
			if (entity.entityOrganizers.get(counter) == user) {
				access = true;
			}
		}
		// boolean canAccess=false;
		// String theUserType =role;
		// if (theUserType.matches("organizationLead")
		// || access==true||user.email.matches("admin@admin.com")) {
		// canAccess = true;
		// }

		// Permission permission = User.userPermissionInOrganization(user.id,
		// o.id, e.id);
		// String role = permission.aUsertype;
		// String userType = User.userPermissionInOrganization(userId,
		// organization.id);
		String userType = role;
		if (userType.matches("organizationLead")

		|| access == true || user.email.matches("admin@admin.com")) {

			authorized = true;
		}

		else {
			authorized = false;
		}
		boolean status = false;
		// (userPermissionInOrganization(uId, o.id)=="IdeaDeveloper"||
		// userPermissionInOrganization(uId, o.id)=="Blocked");
		if (entity.isLocked)
			status = true;
		else
			status = false;
		boolean isFound = false;
		for (int j = 0; j < organization.getEntities().size(); j++) {
			Entities e = organization.getEntities().get(j);
			for (int k = 0; k < e.entityOrganizers.size(); k++) {
				if (user.equals(e.entityOrganizers.get(k)))
					isFound = true;
			}
		}
		boolean isBlocked = false;
		for (int i = 0; i < organization.blockedUsers.size(); i++) {
			if (user.equals(organization.blockedUsers.get(i)))
				isBlocked = true;
		}

		Long organizationId = entity.organization.id;
		render(entity, status, isSubscriber, alluser, permit, organization,
				authorized, user, role, isFound, organizationId, isBlocked,
				canInviteOrganizers, assignOrganizer, blockIdeaDeveloper);
	}

	public static void viewEntityNoPermit(Long id) {
		Entities entity = Entities.findById(id);
		render(entity);
	}

	/*
	 * public static void viewTopicRelation(Long id) { Topic t =
	 * Topic.findById(id); List <Relation> topicRelations = t.getTopics();
	 * render(topicRelations); }
	 */

	/**
	 * adds a user to subscriber list
	 * 
	 * @author Sara Assem
	 * @params Long entityId id of the entity
	 */
	public static void addSubscriber(Long entityid) {
		Entities entity = Entities.findById(entityid);
		String idstring = session.get("userId");
		Long userid = Long.parseLong(idstring);
		User user = User.findById(userid);
		entity.addUserToSubscribers(user);
		user.subscriberentities.add(entity);
		entity.save();
		user.save();
		viewEntity(entityid);

	}

	/**
	 * removes user from subscriber list
	 * 
	 * @author Sara Assem
	 * @params Long id id of the entity
	 */

	public static void removeSubscriber(Long entityid) {
		Entities entity = Entities.findById(entityid);
		String idstring = session.get("userId");
		Long userid = Long.parseLong(idstring);
		User user = User.findById(userid);
		entity.removeUserFromSubscribers(user);
		user.subscriberentities.add(entity);
		entity.save();
		user.save();
		viewEntity(entityid);
	}

	/**
	 * allEntitiesofOrg takes input organization id and draft that will be
	 * published and gets all the entities in this organization to publish draft
	 * as topic
	 * 
	 * @param id
	 *            Organization id
	 * @param draft
	 *            draft that will be published
	 * @author Heba khattab
	 */
	public static void allEntitiesOfOrg(Long id, Long draft_id) {
		Organization org = Organization.findById(id);
		List entity = org.allEntities;
		render(entity, draft_id);
	}

	// /**
	// * allEntitiesofOrgtopic takes input organization id and draft that will
	// be
	// * published and gets all the entities in this organization to publish
	// draft
	// * as idea
	// *
	// * @param id
	// * Organization id
	// * @param draft
	// * draft to be published
	// * @author Heba khattab
	// */
	//
	// public static void allEntitiesOfOrgTopic(Long id, Draft draft) {
	// // id = (long)3;
	// Organization org = Organization.findById(id);
	// List entity = org.allEntities;
	// render(entity, draft);
	// }

	/**
	 * a method that deletes existing entities in an organization.
	 * 
	 * @param entityId
	 *            the entity_id is the auto-generated identification of the
	 *            entity
	 * 
	 * @author Amr El Salanekly
	 */

	public static void showDeleted(long entityId) {

		Entities entity = Entities.findById(entityId);
		List<Topic> topicList = Topic.find("byEntity_id", entityId).fetch();
		Log log = new Log(entity.organization, entity.organization.lead,
				" has deleted the Entity of title: " + entity.entityName
						+ " in the organization.");
		log.save();

		if (entity.relationList.size() != 0) {
			for (int i = 0; i < entity.relationList.size(); i++) {
				entity.relationList.get(i).unassignEntityRelation();
			}

		}
		for (int k = 0; k < topicList.size(); k++) {
			if (topicList.get(k).relationList.size() != 0) {
				for (int i = 0; i < topicList.get(k).relationList.size(); i++) {
					topicList.get(k).relationList.get(i)
							.unassignTopicRelation();
				}
			}
		}
		for (int i = 0; i < topicList.size(); i++) {
			List<Idea> ideaList = Idea.find("byTopic_id", topicList.get(i).id)
					.fetch();

			for (int j = 0; j < ideaList.size(); j++) {
				List<Comment> commentList = Comment.find("byIdea_id",
						ideaList.get(j).id).fetch();
				for (int k = 0; k < commentList.size(); k++) {
					commentList.get(k).delete();
				}
				ideaList.get(j).delete();
			}
			topicList.get(i).delete();
		}
		entity.delete();

	}

	/**
	 * takes an id and find an entity by this id then call a method in the model
	 * to lock this entity
	 * 
	 * 
	 * @param Takes
	 *            the id of the entity to be locked
	 * @author Mohamed Abdel Kader
	 */
	public static void lockEntity(Long entityId) {
		Entities entity = Entities.findById(entityId);
		entity.lockEntity(entity);

	}

	/**
	 * takes an id and find an entity by this id then call a method in the model
	 * to unlock this entity
	 * 
	 * @param Takes
	 *            the id of the entity to be locked
	 * @author Mohamed Abdel Kader
	 */

	public static void unlockEntity(Long entityId) {
		System.out.println("I unlocked the entity");
		Entities entity = Entities.findById(entityId);

		entity.unlockEntity(entity);

	}

	/**
	 * renders page showIdeaDevelopersInOrg.html that shows all the users in
	 * organization and loops on the list of entity organizers and removes them
	 * from the list of users shown here in order to assign them to this entity
	 * 
	 * @see showAllIdeaDeveloper.html
	 * 
	 * @param long Id Id of the entity
	 * 
	 * @author noha wafa
	 * 
	 * 
	 * 
	 */
	public static void showIdeaDevelopersInOrg(Long Id) {

		Entities e = Entities.findById(Id);
		Organization org = e.organization;
		List<User> users = org.getOrgMembers();
		for (int i = 0; i < users.size(); i++) {
			for (int j = 0; j < e.entityOrganizers.size(); j++) {
				if (users.get(i).equals(e.entityOrganizers.get(j))) {
					users.remove(i);
				}
			}
		}
		String idstring = session.get("userId");
		Long id1 = Long.parseLong(idstring);
		User user = User.findById(id1);

		render(users, e);

	}

	/**
	 * takes the user to be assigned and renders page assignedOrganizer.html and
	 * saves the organizers assigned in the entity organizers list
	 * 
	 * @see assignedOrganizer.html where the user sees that the organizer has
	 *      been successfully assigned
	 * 
	 * @param string
	 *            name name of the user
	 * 
	 * @param long Id Id of the user
	 * 
	 * @param long eid Id of the entity
	 * 
	 * 
	 * @author noha wafa
	 * 
	 * 
	 * 
	 */

	public static void assignedOrganizer(String name, Long eid, Long id) {
		User user = User.findById(id);
		Entities e = Entities.findById(eid);
		Organization organization = e.organization;
		// organization.orgMembers.remove(user);
		e.entityOrganizers.add(user);
		user.organization.add(organization);
		Long leadId = Long.parseLong(session.get("userId"));
		User lead = User.findById(leadId);
		Permission permission = lead.userPermissionInOrganization(id,
				organization.id);
		permission.aUserType = "organizer";
		permission.save();
		Permission permissionEntity = new Permission("organizer", organization,
				user, e);
		permissionEntity.save();
		e.save();
		// Permission permission = new Permission("organizer", organization,
		// user, e);
		// permission.aUsertype = "organizer";
		permission.save();
		organization.save();

		e.organization.save();

		user.save();
		/*
		 * Permission prevOrg=user.userPermissionInOrganization(id,
		 * e.organization.id); Permission prevEnt=user.userPermissionInEntity(id
		 * ,e.organization.id,eid); if(prevOrg.aUsertype=="ideadeveloper")
		 * if(prevEnt.aUsertype=="ideadeveloper") {
		 * prevOrg.aUsertype="organizer"; prevEnt.aUsertype="organizer"; }
		 * e.save(); prevOrg.save(); prevEnt.save();
		 */

		render(name);
	}

	/**
	 * shows users in organization and renders showIdeaDevelopersInEntity html
	 * page where all the users in orgnization are displayed looping on entity
	 * organizers list to be able to not show them in this view as we only want
	 * to block ideadevelopers
	 * 
	 * 
	 * @see showIdeaDevelopersInEntitiy.html
	 * 
	 * @param Long
	 *            Id which is the entity which is user is going to follow
	 * 
	 * @author noha wafa
	 * 
	 * 
	 * 
	 */
	public static void showIdeaDevelopersInEntity(Long Id) {
		Entities e = Entities.findById(Id);
		Organization org = e.organization;
		List<User> users = org.getOrgMembers();

		for (int i = 0; i < users.size(); i++) {
			for (int j = 0; j < e.entityOrganizers.size(); j++) {
				if (users.get(i) == e.entityOrganizers.get(j)) {
					users.remove(i);
				}
			}
		}
		render(users, e);
	}

	/**
	 * takes the user and renders the name of the user who will be blocked and
	 * add the user to a list of blocked users
	 * 
	 * @see userblocked.html
	 * 
	 * @param String
	 *            name which is the name of the user that has been blocked
	 * @param Long
	 *            eid which is the entity which is user is followed
	 * @param Long
	 *            id which is the user id whom would be blocked
	 * 
	 * @author noha wafa
	 * 
	 * 
	 * 
	 */

	public static void userblocked(String name, Long eid, Long id) {
		User user = User.findById(id);
		Entities e = Entities.findById(eid);
		Organization org = e.organization;
		e.organization.orgMembers.remove(user);
		e.organization.blockedUsers.add(user);
		user.organization.remove(org);
		org.save();
		e.save();
		user.save();

		render(name, e);

	}

}
